#include "serial_app.h"
#include "at32f435_437.h"
#include "board.h"
#include "config_api.h"
#include "gb_15322_pal.h"
#include "manager_queue.h"
#include "manager_queue_comm.h"
#include "manager_task.h"
#include "module_queue_struct.h"
#include "gateway_manager.h"
#include "transmit_manager.h"
#include "led_manager.h"
#include "uc_log.h"
#include <rtconfig.h>
#include <rtdevice.h>
#include <rthw.h>
#include <rtthread.h>
#include <stdio.h>

////////////////////////////////////////////////////////////////////////////////

#define SERIAL_NAME_LEN (8)
// 高电平保持4s复位
#define HLK_B26_BT_RST_PIN GET_PIN(D, 0)
// 设备使能引脚
#define HLK_B26_BT_EN_PIN GET_PIN(G, 7)

#define ESP32C2_BT_EN_PIN GET_PIN(A, 6)

#define RS485_EN_PIN GET_PIN(E, 14)
// 485收发指示引脚
#define RS485_RT_PIN GET_PIN(E, 15)

#define RS485_RX() rt_pin_write(RS485_RT_PIN, PIN_HIGH)
#define RS485_TX() rt_pin_write(RS485_RT_PIN, PIN_LOW)

#define COM_DEV_ENABLE(pin) rt_pin_write(pin, PIN_HIGH)
#define COM_DEV_DISABLE(pin) rt_pin_write(pin, PIN_LOW)

typedef enum
{
    USE_BT_UNKNOWN = 0,
    USE_BT_HLK_B26,
    USE_BT_ESP32C2,
} use_bt_type_t;

typedef struct serial_recv_proce
{
    // unsigned int dfe_count;
    char rx_buffer[USER_COM_BUFF_SIZE];
    unsigned short rx_length;
    // unsigned short all_rx_length;
    /*0: less than 1k data; 1: more than 1k data, up to 32k, save to flash*/
    // signed char oversize_flag;
    signed char gb15322_flag;
    signed char gb15322_allow;
    signed short head_pos;
    // signed short ready_detect_pos;
    signed short tail_pos;
} serial_rx_proce_t;

typedef struct serial_resource
{
    int module_id;
    char name[SERIAL_NAME_LEN];
    void *handle;
    serial_rx_proce_t serial_recv;
    struct serial_configure cfg;
} serial_resource_t;

/* 串口接收消息结构 */
typedef struct rx_msg
{
    rt_device_t dev;
    rt_size_t size;
} rx_msg_t;

static serial_resource_t s_serial_res[] = {
    {SERIAL_DEBUG_MANAGER_MODULE, RT_CONSOLE_DEVICE_NAME, NULL, {0}, DEBUG_CONFIG},
#ifdef UC_GATEWAY_HARDWARE
    {SERIAL_485_MANAGER_MODULE, USER_COM_485_NAME, NULL, {0}, RS485_CONFIG},
    {BT_MANAGER_MODULE, USER_COM_BT_NAME, NULL, {0}, BT_CONFIG},
    {SERIAL_UART_MANAGER_MODULE, USER_COM_UART_NAME, NULL, {0}, UART_CONFIG},
#endif
};

#define SERIAL_RES_SIZE (sizeof(s_serial_res) / sizeof(s_serial_res[0]))

/**
 * @brief 串口 消息队列
 */
static void *s_serial_queue = RT_NULL;
static void *s_serial_tx_queue = RT_NULL;

static rt_mutex_t s_serial_mutex = RT_NULL;

/* 邮箱控制块 */
static struct rt_mailbox s_serial_shell_mb;
/* 用于放邮件的内存池 */
#define MB_SIZE 128
static char g_serial_shell_mb_pool[MB_SIZE * 4];

static use_bt_type_t g_use_bt_type = USE_BT_UNKNOWN;

////////////////////////////////////////////////////////////////////////////////

// The function used to clean the parameters of the serial port callback function
static void serial_init_param(serial_rx_proce_t *rx_proce_para)
{
    // Set the parameters of the serial port callback function to 0
    rt_memset(rx_proce_para, 0, sizeof(serial_rx_proce_t));
    // Set the head and tail positions of the queue to -1
    rx_proce_para->head_pos = -1;
    rx_proce_para->tail_pos = -1;
}

static int user_com_tx(serial_resource_t *res_p, unsigned char *data, unsigned int len)
{
    int ret_size = 0;
    // Check if the data is valid
    if ((RT_NULL == res_p) || (RT_NULL == res_p->handle) || (RT_NULL == data) || (len < 1))
    {
        TRACE_E("user_com_tx input param error");
        return ret_size;
    }
    if (SERIAL_485_MANAGER_MODULE == res_p->module_id)
    {
        rt_mutex_take(s_serial_mutex, RT_WAITING_FOREVER);
        RS485_TX();
    }

    ret_size = rt_device_write(res_p->handle, 0, data, len);

    if (SERIAL_485_MANAGER_MODULE == res_p->module_id)
    {
        RS485_RX();
        rt_mutex_release(s_serial_mutex);
    }
    return ret_size;
}

static rt_err_t user_com_rx(rt_device_t dev, rt_size_t size)
{
    rt_err_t result = -RT_ERROR;
    int i = 0;
    int src_module = 0;

    // Declare a message struct to store the data received
    static rx_msg_t msg[SERIAL_RES_SIZE] = {{0}};
    static module_queue_message_t msg_queue[SERIAL_RES_SIZE] = {{0}};

    // Store the device and size of the message in the message struct
    for (i = 0; i < SERIAL_RES_SIZE; i++)
    {
        if (dev == s_serial_res[i].handle)
        {
            msg[i].dev = dev;
            msg[i].size = size;
            src_module = s_serial_res[i].module_id;
            break;
        }
    }
    if (i >= SERIAL_RES_SIZE)
    {
        return result;
    }

    // Send the message to the receive message queue
    result = module_queue_send_static_data(s_serial_queue,
                                           src_module,
                                           SERIAL_MANAGER_MODLE,
                                           SERIAL_RECV_DATA,
                                           (void *)&msg[i],
                                           (void *)&msg_queue[i]);
    // Return the result of the operation
    return result;
}

static int serial_app_bt_at_send_cmd(serial_resource_t *res_p, char *at_cmd, char *at_cmd_ack, char *at_response)
{
    int ret = 0;
    int len = 0;
    int bt_read_len = 0;
    char bt_read_data = 0;
    char bt_read_buf[256] = {0};
    rt_tick_t current_time;

    ret = serial_write(BT_MANAGER_MODULE, at_cmd, rt_strlen(at_cmd));
    if (ret != rt_strlen(at_cmd))
    {
        return -RT_ERROR;
    }

    rt_memset(bt_read_buf, 0, sizeof(bt_read_buf));

    current_time = rt_tick_get();
    while (rt_tick_get() - current_time < 1000)
    {
        bt_read_data = 0;
        len = rt_device_read(res_p->handle, 0, &bt_read_data, 1);
        if (bt_read_data != 0)
        {
            bt_read_buf[bt_read_len] = bt_read_data;
            bt_read_len += len;
        }

        if (RT_NULL != rt_strstr(bt_read_buf, at_cmd_ack))
        {
            rt_thread_mdelay(100);
            len = rt_device_read(res_p->handle, 0, &bt_read_buf[bt_read_len], 256);
            bt_read_len += len;
            if (RT_NULL != at_response)
            {
                rt_memcpy(at_response, bt_read_buf, (bt_read_len - rt_strlen(at_cmd_ack) - 4));
            }
            return RT_EOK;
        }
    }

    return -RT_ERROR;
}

static int serial_app_bt_at_mode_entry(void)
{
    // 蓝牙模块进入AT模式
    if (g_use_bt_type == USE_BT_HLK_B26)
    {
        rt_pin_mode(HLK_B26_BT_RST_PIN, PIN_MODE_OUTPUT);
        rt_pin_write(HLK_B26_BT_RST_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(HLK_B26_BT_RST_PIN, PIN_LOW);
        rt_thread_mdelay(300);
    }
    else if (g_use_bt_type == USE_BT_ESP32C2)
    {
        rt_pin_mode(ESP32C2_BT_EN_PIN, PIN_MODE_OUTPUT);
        rt_pin_write(ESP32C2_BT_EN_PIN, PIN_LOW);
        rt_thread_mdelay(200);
        rt_pin_write(ESP32C2_BT_EN_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
    }
    else
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

static int serial_app_bt_at_mode_exit(serial_resource_t *res_p)
{
    int ret = 0;
    char at_exit_cmd[32];

    rt_memset(at_exit_cmd, 0, sizeof(at_exit_cmd));

    if (g_use_bt_type == USE_BT_HLK_B26)
    {
        rt_sprintf(at_exit_cmd, "AT+REBOOT=1\r\n");
    }
    else if (g_use_bt_type == USE_BT_ESP32C2)
    {
        rt_sprintf(at_exit_cmd, "AT+BLESPP\r\n");
    }
    else
    {
        return -RT_ERROR;
    }

    ret = serial_app_bt_at_send_cmd(res_p, at_exit_cmd, "OK", RT_NULL);
    if (ret != RT_EOK)
    {
        TRACE_E("exit at mode error");
    }

    return ret;
}

static int hlk_b26_capture_ble_mac(serial_resource_t *res_p)
{
    int ret = RT_ERROR;
    int i = 0;
    rt_tick_t current_time = 0;
    char bt_mac_get_cmd[] = "AT+MAC=?\r\n";
    char bt_ver_get_cmd[] = "AT+VER=?\r\n";
    char bt_slave_mode_cmd[] = "AT+ROLE=1\r\n";
    char bt_at_response[256] = {0};
    char *str_point = RT_NULL;

    // 默认波特率115200.发送测试at指令，判断波特率是否为115200.如果指令成功，后面需要修改波特率。
    serial_app_bt_at_send_cmd(res_p, bt_mac_get_cmd, "OK", bt_at_response);

    str_point = rt_strstr(bt_at_response, "AT+MAC=");
    if (str_point != RT_NULL)
    {
        str_point += 7;
        char *bt_mac = rt_calloc(1, 16);
        rt_memcpy(bt_mac, str_point, 12);
        TRACE_D("ble_mac is %s", bt_mac);
        if (rt_memcmp(bt_mac, uc_static_get_gateway_bt_cfg()->mac, 16) != 0)
        {
            module_queue_communication(get_gateway_manager_queue(),
                                       BT_MANAGER_MODULE,
                                       GATEWAY_MANAGER_MODULE,
                                       BT_CFG_SET,
                                       bt_mac);
        }
        else
        {
            rt_free(bt_mac);
            TRACE_D("ble_mac is equal to static data");
        }
    }
    else
    {
        TRACE_E("ble_mac is null");
    }

    // 获取蓝牙固件版本号
    serial_app_bt_at_send_cmd(res_p, bt_ver_get_cmd, "OK", bt_at_response);

    str_point = rt_strstr(bt_at_response, "AT+VER=");
    if (str_point != RT_NULL)
    {
        str_point += 7;
        TRACE_D("ble soft version is %s", str_point);
    }
    else
    {
        TRACE_E("ble soft version is null");
    }

    // 进入蓝牙从机模式
    serial_app_bt_at_send_cmd(res_p, bt_slave_mode_cmd, "OK", RT_NULL);

    return ret;
}

#if 0
static int change_ble_baud(serial_resource_t *res_p)
{
    int ret = RT_ERROR;
    char str[] = "AT+BAND=?\r\n";
    char str1[] = "AT+BAND=230400\r\n";
    char str2[] = "AT+REBOOT=1\r\n";
    char str3[] = "AT+MAC=?\r\n";
    char at_result[10] = {0};
    char mac_result[30] = {0};

#if 1
        // 蓝牙模块进入AT模式
        rt_pin_mode(HLK_B26_BT_RST_PIN, PIN_MODE_OUTPUT);
        rt_pin_write(HLK_B26_BT_RST_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(HLK_B26_BT_RST_PIN, PIN_LOW);
        rt_thread_mdelay(300);
#endif

    // 默认波特率115200.发送测试at指令，判断波特率是否为115200.如果指令成功，后面需要修改波特率。
    serial_write(BT_MANAGER_MODULE, str, (sizeof(str) - 1));
    rt_tick_t current_time = rt_tick_get();
    // read
    while(rt_tick_get() - current_time < 200)
    {
        rt_device_read(res_p->handle, 0, at_result, sizeof(at_result)/sizeof(at_result[0]));
    }
    rt_thread_mdelay(1);
    TRACE_D("first ble_response is %s", at_result);

    // if ( read at resut)
    if(rt_strncmp(at_result, "OK", 2) == 0)
    {// 如果成功，则说明默认波特率为115200.需要修改
        // 发送修改蓝牙模块波特率命令230400
        serial_write(BT_MANAGER_MODULE, str1, (sizeof(str1) - 1));
        // 读取结果
        current_time = rt_tick_get();
        while(rt_tick_get() - current_time < 200)
        {
            rt_device_read(res_p->handle, 0, at_result, sizeof(at_result)/sizeof(at_result[0]));
        }
        rt_thread_mdelay(1);
        TRACE_D("first recuperative ble_response is %s", at_result);

        serial_write(BT_MANAGER_MODULE, str3, (sizeof(str3) - 1));
        current_time = rt_tick_get();
        // read
        while(rt_tick_get() - current_time < 200)
        {
            rt_device_read(res_p->handle, 0, mac_result, sizeof(mac_result)/sizeof(mac_result[0]));
        }
        rt_thread_mdelay(1);
        TRACE_D("ble_mac_addr is %s", mac_result);

        // 重启蓝牙模块
        serial_write(BT_MANAGER_MODULE, str2, (sizeof(str2) - 1));
        rt_thread_mdelay(1000);
        // 修改at32波特率为230400
        res_p->cfg.baud_rate = BAUD_RATE_230400;
        ret = rt_device_control(res_p->handle, RT_DEVICE_CTRL_CONFIG, &res_p->cfg);
        // 返回成功
        return RT_EOK;
    }
    else
    { //失败则确实波特率是否为230400
        // 设置波特率为230400
        res_p->cfg.baud_rate = BAUD_RATE_230400;
        ret = rt_device_control(res_p->handle, RT_DEVICE_CTRL_CONFIG, &res_p->cfg);
        // 发送测试at指令
        serial_write(BT_MANAGER_MODULE, str, (sizeof(str) - 1));
        // 读取at结果
        current_time = rt_tick_get();
        while(rt_tick_get() - current_time < 200)
        {
            rt_device_read(res_p->handle, 0, at_result, sizeof(at_result)/sizeof(at_result[0]));
        }
        rt_thread_mdelay(1);
        TRACE_D("first no_reply ble_response is %s", at_result);

        serial_write(BT_MANAGER_MODULE, str3, (sizeof(str3) - 1));
        current_time = rt_tick_get();
        // read
        while(rt_tick_get() - current_time < 200)
        {
            rt_device_read(res_p->handle, 0, mac_result, sizeof(mac_result)/sizeof(mac_result[0]));
        }
        rt_thread_mdelay(1);
        TRACE_D("ble_mac_addr is %s", mac_result);

        //重启蓝牙模块
        serial_write(BT_MANAGER_MODULE, str2, (sizeof(str2) - 1));

        // 判断结果。 如果结果正确，则波特率已经是230400，不需要再次修改波特率；如果失败，报错。
        if(rt_strncmp(at_result, "OK", 2) == 0)
        {// 返回成功
            TRACE_D("change baud success");
            return RT_EOK;
        }
        else
        {// 返回失败
            TRACE_E("change baud error");
            return RT_ERROR;
        }
    }
}
#endif

static int esp32c2_capture_ble_mac(serial_resource_t *res_p)
{
    int ret = RT_ERROR;
    int i = 0;
    rt_tick_t current_time = 0;
    char bt_mac_get_cmd[] = "AT+BLEADDR?\r\n";
    char bt_broadcast_cmd[] = "AT+BLEADVDATAEX=";
    char bt_tx_power_cmd[] = "AT+RFPOWER=";
    char bt_at_send[256] = {0};
    char bt_at_response[256] = {0};
    char *str_point = RT_NULL;
    gw_base_cfg_t *gw_base_cfg = uc_static_get_gateway_base_cfg();

    // 清空缓冲区
    rt_device_read(res_p->handle, 0, bt_at_response, 256);

    // 默认波特率115200.发送测试at指令，判断波特率是否为115200.如果指令成功，后面需要修改波特率。
    serial_app_bt_at_send_cmd(res_p, bt_mac_get_cmd, "OK", bt_at_response);

    str_point = rt_strstr(bt_at_response, "+BLEADDR:");
    if (str_point != RT_NULL)
    {
        str_point += 9;
        char *bt_mac = rt_calloc(1, 16);
        sscanf(str_point, "\"%02s:%02s:%02s:%02s:%02s:%02s\"", &bt_mac[0], &bt_mac[2], &bt_mac[4], &bt_mac[6], &bt_mac[8], &bt_mac[10]);
        TRACE_D("ble_mac is %s", bt_mac);
        if (rt_memcmp(bt_mac, uc_static_get_gateway_bt_cfg()->mac, 16) != 0)
        {
            module_queue_communication(get_gateway_manager_queue(),
                                       BT_MANAGER_MODULE,
                                       GATEWAY_MANAGER_MODULE,
                                       BT_CFG_SET,
                                       bt_mac);
        }
        else
        {
            rt_free(bt_mac);
            TRACE_D("ble_mac is equal to static data");
        }
    }
    else
    {
        TRACE_E("ble_mac is null");
    }

    // 设置广播参数
    rt_memset(bt_at_send, 0, sizeof(bt_at_send));
    char *bt_broadcast_name = rt_calloc(sizeof(char), 16);
    rt_sprintf(bt_broadcast_name, "GW-%u", gw_base_cfg->dev_id);
    rt_sprintf(bt_at_send, "%s\"%s\",\"%s\",\"%s\",%d\r\n", bt_broadcast_cmd, bt_broadcast_name, "NULL", "NLL", 1);
    ret = serial_app_bt_at_send_cmd(res_p, bt_at_send, "OK", RT_NULL);
    rt_free(bt_broadcast_name);

    if (ret != RT_EOK)
    {
        TRACE_E("set ble broadcast error");
        return ret;
    }

    // 设置发射功率
    rt_memset(bt_at_send, 0, sizeof(bt_at_send));
    rt_sprintf(bt_at_send, "%s%d\r\n", bt_tx_power_cmd, 15);
    ret = serial_app_bt_at_send_cmd(res_p, bt_at_send, "OK", RT_NULL);

    if (ret != RT_EOK)
    {
        TRACE_E("set ble tx power error");
        return ret;
    }

    return RT_EOK;
}

static use_bt_type_t serial_app_bt_type_get(void)
{
    char *gw_hw_version = uc_static_get_gateway_base_cfg()->hardware_version;
    use_bt_type_t bt_type = USE_BT_UNKNOWN;

    if (rt_strcmp(gw_hw_version, CFG_HARDWARE_VERSION_V1_3) == 0)
    {
        bt_type = USE_BT_HLK_B26;
    }
    else if (rt_strcmp(gw_hw_version, CFG_HARDWARE_VERSION_V1_5) == 0)
    {
        bt_type = USE_BT_ESP32C2;
    }
    else if (rt_strcmp(gw_hw_version, CFG_HARDWARE_VERSION_V1_6) == 0)
    {
        bt_type = USE_BT_ESP32C2;
    }

    return bt_type;
}

static void serial_app_bt_init(serial_resource_t *res_p)
{
    int ret = 0;

    if (g_use_bt_type == USE_BT_HLK_B26)
    {
        rt_pin_mode(HLK_B26_BT_EN_PIN, PIN_MODE_OUTPUT);
        COM_DEV_ENABLE(HLK_B26_BT_EN_PIN);

        serial_app_bt_at_mode_entry();
        ret = hlk_b26_capture_ble_mac(res_p);
#if 0
        ret = change_ble_baud(res_p);
        if(0 != ret)
        {
            TRACE_E("change ble baud error");
            return ret;
        }
#endif
    }
    else if (g_use_bt_type == USE_BT_ESP32C2)
    {
        serial_app_bt_at_mode_entry();
        esp32c2_capture_ble_mac(res_p);
    }
    else
    {
        TRACE_E("unknown hw version, bt init failed");
        return;
    }

    serial_app_bt_at_mode_exit(res_p);
}

/**
 * @brief  切换485串口波特率
 *
 * @param  baud_rate 波特率
 * @return int 0:成功，其他：失败
 */
int serial_app_485_baud_rate_set(unsigned int baud_rate)
{
    serial_resource_t *res_p = RT_NULL;
    for (int i = 0; i < SERIAL_RES_SIZE; i++)
    {
        if (s_serial_res[i].module_id == SERIAL_485_MANAGER_MODULE)
        {
            res_p = &s_serial_res[i];
            break;
        }
    }

    if (baud_rate == 0)
    {
        baud_rate = BAUD_RATE_9600;
        TRACE_E("baud_rate is 0, recover to default %d", baud_rate);
    }

    res_p->cfg.baud_rate = baud_rate;
    TRACE_I("serial_app_485_baud_rate_set %d", baud_rate);

    return rt_device_control(res_p->handle, RT_DEVICE_CTRL_CONFIG, &res_p->cfg);
}

static int user_com_init(serial_resource_t *res_p)
{
    int ret = RT_ERROR;
    if (RT_NULL == res_p)
        return ret;
    res_p->handle = rt_device_find(res_p->name);
    TRACE_D("user_com_init %s", res_p->name);

    if (res_p->handle == RT_NULL)
    {
        TRACE_E("%s handle == NULL", res_p->name);
        return -RT_ERROR;
    }

    switch (res_p->module_id)
    {
    case SERIAL_DEBUG_MANAGER_MODULE:
        ret = RT_EOK;
        break;
    default:
        /* using DMA mode first */
        ret = rt_device_open(res_p->handle, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
        /* using interrupt mode when DMA mode not supported */
        if (ret == -RT_EIO)
        {
            ret = rt_device_open(res_p->handle, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
        }
        break;
    }

    RT_ASSERT(ret == RT_EOK);

    switch (res_p->module_id)
    {
    case SERIAL_DEBUG_MANAGER_MODULE:
        break;
    case SERIAL_485_MANAGER_MODULE:
        ret = serial_app_485_baud_rate_set(uc_static_get_gateway_uart_485_cfg()->baud_rate);
        break;
    case BT_MANAGER_MODULE:
        g_use_bt_type = serial_app_bt_type_get();
        switch (g_use_bt_type)
        {
        case USE_BT_HLK_B26:
            res_p->cfg.baud_rate = BAUD_RATE_115200;
            break;
        case USE_BT_ESP32C2:
            res_p->cfg.baud_rate = BAUD_RATE_460800;
            break;
        default:
            break;
        }
        ret = rt_device_control(res_p->handle, RT_DEVICE_CTRL_CONFIG, &res_p->cfg);
        break;
    default:
        ret = rt_device_control(res_p->handle, RT_DEVICE_CTRL_CONFIG, &res_p->cfg);
        break;
    }

    if (ret != RT_EOK)
    {
        TRACE_E("%s control failed", res_p->name);
        return ret;
    }

    switch (res_p->module_id)
    {
    case SERIAL_485_MANAGER_MODULE:
        rt_pin_mode(RS485_EN_PIN, PIN_MODE_OUTPUT);
        COM_DEV_ENABLE(RS485_EN_PIN);
        rt_pin_mode(RS485_RT_PIN, PIN_MODE_OUTPUT);
        RS485_RX();
        break;
    case BT_MANAGER_MODULE:
        serial_app_bt_init(res_p);
        send_led_event(LED_BLUE, LED_E_NORMAL);
        break;
    default:
        break;
    }

    // set the rx indicate
    TRACE_D("handle rt_device_set_rx_indicate");
    rt_device_set_rx_indicate(res_p->handle, user_com_rx);

    serial_init_param(&res_p->serial_recv);
    return RT_EOK;
}

static int serial_res_init(void)
{
    for (int i = 0; i < SERIAL_RES_SIZE; i++)
    {
        user_com_init(&s_serial_res[i]);
    }
    // TRACE_D("SERIAL_RES_SIZE %d", SERIAL_RES_SIZE);
    return 0;
}

////////////////////////////////////////////////////////////////////////////////

static void serial_tx_app_task(void *parameter)
{
    module_queue_message_t *page;
    unsigned int address = uc_static_get_gateway_base_cfg()->dev_id;

    while (1)
    {
        if (manager_recv_queue(s_serial_tx_queue, (void *)&page, UC_QUEUE_WAITING_FOREVER))
        {
            continue;
        }
        if (RT_NULL == page)
        {
            continue;
        }
        uplink_transmit_manager(address, page->dest_task, page->cmd, page->data);
        // 释放内存
        if (RT_NULL != page->data)
        {
            rt_free(page->data);
            page->data = RT_NULL;
        }
        rt_free(page);
        page = RT_NULL;
    }
}

static int serial_create_tx_task(void)
{
    static void *serail_handle = RT_NULL;
    if (0 != manager_thread_create(&serail_handle, "u_tx_t", serial_tx_app_task, RT_NULL, 512, RT_THREAD_PRIORITY_MAX / 3 + 1, 5))
    {
        TRACE_E("manager_thread_create serail_app task error");
        return 1;
    }
    rt_thread_startup((rt_thread_t)serail_handle);
    return 0;
}

static void user_data_trans(serial_resource_t *res_p)
{
    if (RT_NULL == res_p)
        return;
    TRACE_D("user_data_trans get (%d) data: %s", res_p->serial_recv.rx_length, res_p->serial_recv.rx_buffer);
#if 0
    // TRACE_D("user_data_trans rx_length %d", rx_length);
    t_wiota_page *page;
    unsigned int dest_addr = 0;
    int data_len = rx_length - sizeof(dest_addr);

    // test_data_print("user_data_trans", rx_buffer, (int) rx_length);

    // copy dest_addr from rx_buffer
    rt_memcpy(&dest_addr, rx_buffer, sizeof(dest_addr));

    // add crc data of 2 byte
    page = rt_malloc(sizeof(t_wiota_page) + data_len + 2);
    MEMORY_ASSERT(page);

    // copy data from rx_buffer to page->data
    rt_memcpy(page->data, rx_buffer + sizeof(dest_addr), data_len);
    page->send_resp_cb = RT_NULL;

    //TRACE_D("user_data_trans dest_addr 0x%x", dest_addr);
    //TRACE_D("user_data_trans page->data %s", page->data);

    // send user data to serial module
    if (module_queue_communication(get_wiota_operation_queue(),
                                   MANAGER_SERIAL_INDENTIFICATION,
                                   MANAGER_WIOTA_INDENTIFICATION,
                                   WIOTA_SEND_USERDATA,
                                   dest_addr,
                                   page, data_len,
                                   0,
                                   MODULE_SEND_QUEUE_TIMEOUT))
    {
        TRACE_E("serial module_queue_communication");
        rt_free(page);
    }
#endif
}

// This function checks if the tail position is within the range of the received data length.
// If it is, it checks if the tail position is 0xEE and if the checksum is valid. If not,
// it sets the GB15322_ALLOW flag to NO_ALLOW and prints out the head and tail positions and the received data length.
static int serial_parse_tail(serial_rx_proce_t *rx_proce)
{
    // Check if the tail position is within the range of the received data length
    if ((rx_proce->tail_pos + 1) <= rx_proce->rx_length)
    {
        // Check if the tail position is 0xEE and if the checksum is valid
        if ((PRO_TAIL == rx_proce->rx_buffer[rx_proce->tail_pos]) &&
            (0 == gb_15322_checksum((unsigned char *)&rx_proce->rx_buffer[rx_proce->head_pos],
                                    rx_proce->tail_pos - rx_proce->head_pos)))
        {
            return 0;
        }
        else
        {
            // If not, set the GB15322_ALLOW flag to NO_ALLOW and print out the head and tail positions and the received data length
            rx_proce->gb15322_allow = UC_GB15322_NO_ALLOW;
            TRACE_E("head_pos %d tail_pos %d rx_length %d g15322_data_len %d",
                    rx_proce->head_pos,
                    rx_proce->tail_pos,
                    rx_proce->rx_length,
                    gb_15322_get_len((unsigned char *)&rx_proce->rx_buffer[rx_proce->head_pos]));
            TRACE_E("tail no 0xEE val 0x%x", rx_proce->rx_buffer[rx_proce->tail_pos]);
        }
    }
    // Return 1 if the tail position is not within the range of the received data length
    return 1;
}

static int serial_complete_data_proc(int src_module, serial_rx_proce_t *rx_proce)
{
    // check if the tail is 0
    int ret = 1;
    if (RT_NULL == rx_proce)
    {
        return ret;
    }
    ret = serial_parse_tail(rx_proce);
    if (0 == ret)
    {
        downlink_transmit_manager(
            src_module,
            (unsigned char *)&rx_proce->rx_buffer[rx_proce->head_pos],
            rx_proce->tail_pos - rx_proce->head_pos + 1);
        // init data
        serial_init_param(rx_proce);
    }
    return ret;
}

static int serial_read_proc(int src_module, rx_msg_t *msg, serial_rx_proce_t *rx_proce, unsigned int my_addr)
{
    if ((RT_NULL == msg) || (RT_NULL == rx_proce))
        return 1;
    int size = msg->size;
    if ((rx_proce->rx_length + size) >= USER_COM_BUFF_SIZE)
    {
        rx_proce->rx_length = 0;
    }
    int rx_len = rt_device_read(msg->dev,
                                0,
                                &rx_proce->rx_buffer[rx_proce->rx_length],
                                USER_COM_BUFF_SIZE - rx_proce->rx_length);
    if (0 == rx_len)
        return 1;
    rx_proce->rx_length += rx_len;

    // check whether the data is GB15322 format
    if ((rx_proce->rx_length > 10) &&
        (UC_GB15322_ALLOW == rx_proce->gb15322_allow))
    {
        // check whether the data is GB15322 head
        if (UC_GB15322_HEAD == rx_proce->gb15322_flag)
        {
            // find head
            rx_proce->head_pos = gb_15322_head((unsigned char *)rx_proce->rx_buffer,
                                               (unsigned int)rx_proce->rx_length);
            if (-1 != rx_proce->head_pos)
            {
                unsigned short gb_len = gb_15322_get_len((unsigned char *)&rx_proce->rx_buffer[rx_proce->head_pos]);
                // get tail position
                rx_proce->tail_pos = GB18322_LEN_OFFSET + 3 + rx_proce->head_pos + gb_len;

                // check whether the data is complete
                if (0 == serial_complete_data_proc(src_module, rx_proce))
                    return 0;
                // set flag to tail
                rx_proce->gb15322_flag = UC_GB15322_TAIL;
            }
            else
            {
                // set flag to no allow
                // rx_proce->gb15322_allow = UC_GB15322_NO_ALLOW;
                TRACE_E("serial_read_proc NO_ALLOW\n");
            }
        }
        // check whether the data is GB15322 tail
        else if (UC_GB15322_TAIL == rx_proce->gb15322_flag)
        {
            // check whether the data is complete
            if (0 == serial_complete_data_proc(src_module, rx_proce))
                return 0;
        }
    }
    return 1;
}

static int serial_app_recv_data(module_queue_message_t *page, unsigned int address)
{
    if ((RT_NULL == page) || (RT_NULL == page->data))
    {
        return 1;
    }
    rx_msg_t *msg = (rx_msg_t *)page->data;
    serial_rx_proce_t *recv_proce = RT_NULL;
    int i = 0;
    if (msg->size < 1)
    {
        return 1;
    }
    for (i = 0; i < SERIAL_RES_SIZE; i++)
    {
        if (msg->dev == s_serial_res[i].handle)
        {
            recv_proce = &(s_serial_res[i].serial_recv);
            break;
        }
    }
    if ((i >= SERIAL_RES_SIZE) || (RT_NULL == recv_proce))
    {
        return 1;
    }
    switch (page->cmd)
    {
    case SERIAL_RECV_DATA:
        // Read the data
        serial_read_proc(page->src_task, msg, recv_proce, address);
        break;
    default:
        break;
    }

    if (SERIAL_DEBUG_MANAGER_MODULE == page->src_task)
    {
        if (recv_proce->rx_length == 0)
        {
            return 0;
        }
    }
    else if (SERIAL_485_MANAGER_MODULE == page->src_task)
    {
        if (recv_proce->rx_length == 1)
        {
            rt_mutex_take(s_serial_mutex, RT_WAITING_FOREVER);
        }
        else if (recv_proce->rx_length == 0)
        {
            rt_mutex_release(s_serial_mutex);
        }
    }

    return 1;
}

////////////////////////////////////////////////////////////////////////////////

/**
 * @defgroup    外部接口
 */

char *get_serial_name(int module_id)
{
    for (int i = 0; i < SERIAL_RES_SIZE; i++)
    {
        if (module_id == s_serial_res[i].module_id)
        {
            return s_serial_res[i].name;
        }
    }
    return RT_NULL;
}

void *get_serial_queue(void)
{
    return s_serial_tx_queue;
}

int serial_create_queue(void)
{
    s_serial_queue = manager_create_queue("u_rx_q", 4, 100, UC_SYSTEM_IPC_FLAG_PRIO);
    if (RT_NULL == s_serial_queue)
    {
        TRACE_E("manager_create_queue serial_app error in %s line %d", __FUNCTION__, __LINE__);
        return RT_ERROR;
    }
    s_serial_tx_queue = manager_create_queue("u_tx_q", 4, 100, UC_SYSTEM_IPC_FLAG_PRIO);
    if (RT_NULL == s_serial_tx_queue)
    {
        TRACE_E("manager_create_queue serial_send_app error in %s line %d", __FUNCTION__, __LINE__);
        return RT_ERROR;
    }
    return RT_EOK;
}

int serial_app_finsh_mb_init(void)
{
    rt_err_t result;
    /* 初始化一个 mailbox */
    result = rt_mb_init(&s_serial_shell_mb,
                        "shell_mb",                         /* 名称是 shell_mb */
                        &g_serial_shell_mb_pool[0],         /* 邮箱用到的内存池是 mb_pool */
                        sizeof(g_serial_shell_mb_pool) / 4, /* 邮箱中的邮件数目，因为一封邮件占 4 字节 */
                        RT_IPC_FLAG_FIFO);                  /* 采用 FIFO 方式进行线程等待 */
    if (result != RT_EOK)
    {
        TRACE_E("init serial shell mailbox failed.");
        return -RT_ERROR;
    }
}

int serial_app_finsh_getchar(void)
{
    int ch;

    /* 从邮箱中收取邮件 */
    if (RT_EOK == rt_mb_recv(&s_serial_shell_mb, (rt_uint32_t *)&ch, RT_WAITING_FOREVER))
    {
        return ch;
    }

    return -1;
}

void serial_app_task(void *parameter)
{
    module_queue_message_t *page = RT_NULL;
    rt_err_t result;
    unsigned int address = uc_static_get_gateway_base_cfg()->dev_id;
    unsigned char is_gatewayw_cmd = RT_FALSE;

    TRACE_I("user_com_task running");

    /* 创建一个互斥量 */
    s_serial_mutex = rt_mutex_create("serial_mutex", RT_IPC_FLAG_PRIO);
    if (s_serial_mutex == RT_NULL)
    {
        TRACE_E("create s_serial_mutex failed");
        return;
    }

    serial_res_init();

    serial_create_tx_task();

    module_queue_communication(get_gateway_manager_queue(),
                               BT_MANAGER_MODULE,
                               GATEWAY_MANAGER_MODULE,
                               SERIAL_INIT_FINISH,
                               RT_NULL);

    while (1)
    {
        // Receive data from the message queue
        result = manager_recv_queue(s_serial_queue, (void *)&page, USER_COM_TIMEOUT);
        // TRACE_I("serial_app_task res %d", result);
        if (RT_EOK == result)
        {
            switch (page->src_task)
            {
            case SERIAL_DEBUG_MANAGER_MODULE:
                if (is_gatewayw_cmd == RT_FALSE)
                {
                    unsigned char ch;
                    rt_size_t size = 0;
                    do
                    {
                        size = rt_device_read(s_serial_res[0].handle, -1, &ch, 1);
                        if (size != 0)
                        {
                            if (ch == PRO_HEAD)
                            {
                                serial_rx_proce_t *recv_proce = &(s_serial_res[0].serial_recv);
                                recv_proce->rx_buffer[recv_proce->rx_length] = ch;
                                recv_proce->rx_length += 1;
                                is_gatewayw_cmd = RT_TRUE;
                                break;
                            }
                            rt_mb_send(&s_serial_shell_mb, (unsigned int)ch);
                        }
                    } while (size != 0);
                }
                if (is_gatewayw_cmd = RT_TRUE)
                {
                    if (serial_app_recv_data(page, address) == 0)
                    {
                        is_gatewayw_cmd = RT_FALSE;
                    }
                }
                break;
            case BT_MANAGER_MODULE:
            case SERIAL_485_MANAGER_MODULE:
            case SERIAL_UART_MANAGER_MODULE:
                serial_app_recv_data(page, address);
                break;
            default:
                break;
            }
        }
        else if (-RT_ETIMEOUT == result)
        {
            is_gatewayw_cmd = RT_FALSE;
            for (int i = 0; i < SERIAL_RES_SIZE; i++)
            {
                serial_rx_proce_t *serial_rx = &(s_serial_res[i].serial_recv);

                // Timeout, check if the data is complete
                if ((serial_rx->rx_length > 4) &&
                    (UC_GB15322_NO_ALLOW == serial_rx->gb15322_allow))
                {
                    TRACE_D("manager_recv_queue timeout i %d len %d", i, serial_rx->rx_length);
                    // Send the data to the user
                    // Send the data to the user
                    user_data_trans(&s_serial_res[i]);
                }
                // init the receive process
                serial_init_param(serial_rx);
            }
            rt_mutex_release(s_serial_mutex);
        }
    }
}

int serial_write(int dest_module, unsigned char *data, unsigned int len)
{
    for (int i = 0; i < SERIAL_RES_SIZE; i++)
    {
        if (dest_module == s_serial_res[i].module_id)
        {
            return user_com_tx(&s_serial_res[i], data, len);
        }
    }
    TRACE_E("NO dest_module %d", dest_module);
    return 0;
}
